package com.rongji.dfish.demo.editor.controller;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.rongji.dfish.base.Utils;
import com.rongji.dfish.base.crypt.CryptFactory;
import com.rongji.dfish.base.crypt.JCECryptor;
import com.rongji.dfish.base.crypt.StringCryptor;
import com.rongji.dfish.framework.controller.BaseController;
import com.rongji.dfish.misc.chinese.Trad2SimpConverter;
import com.rongji.dfish.misc.origin.OriginMatcher;
import com.rongji.dfish.ui.Combo;
import com.rongji.dfish.ui.Highlight;
import com.rongji.dfish.ui.Widget;
import com.rongji.dfish.ui.annotation.Data4FlexGrid;
import com.rongji.dfish.ui.annotation.Data4FormPanel;
import com.rongji.dfish.ui.annotation.Data4GridPanel;
import com.rongji.dfish.ui.annotation.Data4GridPanel.ColumnType;
import com.rongji.dfish.ui.annotation.Data4Ui;
import com.rongji.dfish.ui.annotation.NodeType;
import com.rongji.dfish.ui.command.JSCommand;
import com.rongji.dfish.ui.form.Checkboxgroup;
import com.rongji.dfish.ui.form.Combobox;
import com.rongji.dfish.ui.form.DatePicker;
import com.rongji.dfish.ui.form.Linkbox;
import com.rongji.dfish.ui.form.MuldatePicker;
import com.rongji.dfish.ui.form.Onlinebox;
import com.rongji.dfish.ui.form.Password;
import com.rongji.dfish.ui.form.Period;
import com.rongji.dfish.ui.form.Radiogroup;
import com.rongji.dfish.ui.form.Select;
import com.rongji.dfish.ui.form.Spinner;
import com.rongji.dfish.ui.form.Text;
import com.rongji.dfish.ui.form.Textarea;
import com.rongji.dfish.ui.form.Xbox;
import com.rongji.dfish.ui.helper.FlexGrid;
import com.rongji.dfish.ui.helper.FormPanel;
import com.rongji.dfish.ui.helper.GridLayoutFormPanel;
import com.rongji.dfish.ui.helper.GridPanel;
import com.rongji.dfish.ui.layout.HorizontalLayout;
import com.rongji.dfish.ui.layout.VerticalLayout;
import com.rongji.dfish.ui.layout.View;
import com.rongji.dfish.ui.layout.grid.GridColumn;
import com.rongji.dfish.ui.layout.grid.Tr;
import com.rongji.dfish.ui.widget.Button;
import com.rongji.dfish.ui.widget.Html;
import com.rongji.dfish.ui.widget.PageBar;
import com.rongji.dfish.ui.widget.SubmitButton;
@Controller
@RequestMapping("/misc")
public class MiscController  extends BaseController{
	
	@RequestMapping("/findOrigin")
	@ResponseBody
	public Object findOrigin(HttpServletRequest request) throws Exception {
		String src=Utils.getParameter(request, "src");
		OriginMatcher matcher = OriginMatcher.getInstance();
		OriginMatcher.MatchResult mr=matcher.match(src);
		String result="[未知]";
		int conf=0;
		if(mr!=null){
			result=mr.getCode();
			conf=mr.getConfidence();
		}
		return new JSCommand("VM(this).fv('result','"+result+"');VM(this).fv('confidence','"+conf+"');");
	}
	
	@RequestMapping("/chineseC2T")
	@ResponseBody
	public Object chineseC2T(HttpServletRequest request) throws Exception {
		boolean t2c="T2C".equals(request.getParameter("cmd"));
		if(t2c){
			Trad2SimpConverter c=new Trad2SimpConverter();
			String src=Utils.getParameter(request, "TC");
			String res=c.convert(src);
			return new JSCommand("VM(this).fv('SC','"+Utils.escapeXMLword(res)+"')");
		}else{
			Trad2SimpConverter c=new Trad2SimpConverter(Trad2SimpConverter.SIMPLIFIED_TO_TRADITIONAL);
			String src=Utils.getParameter(request, "SC");
			String res=c.convert(src);
			return new JSCommand("VM(this).fv('TC','"+Utils.escapeXMLword(res)+"')");
		}
	}
	
	@RequestMapping("/encrypt")
	@ResponseBody
	public Object encrypt(HttpServletRequest request) throws Exception {
		boolean en="en".equals(request.getParameter("cmd"));
		String src=Utils.getParameter(request, "src");
		Object code=Utils.getParameter(request, "code");
		String alg=request.getParameter("alg");
		String encode=request.getParameter("encode");
		String prs=request.getParameter("prs");
		if(CryptFactory.AES.equals(alg)){
			code=JCECryptor.hex2byte("FE868B7887D68D3D4399EB60810D9631");//密钥
		}else if(CryptFactory.DES.equals(alg)){
			code=JCECryptor.hex2byte("3BDF58838F19161A");//密钥
		}else if(CryptFactory.TRIPLE_DES.equals(alg)){
			code=JCECryptor.hex2byte("EF1C3776A87AE602F1F120613BC1CBF29D9BF26D8062FB40");//密钥
		}else if(CryptFactory.RSA.equals(alg)){
			//
			code=new BigInteger[] {
					new BigInteger("12868221579326205383"),
					new BigInteger("12400495569779260772208470728281091633857262584882396634232537673686136695792012744253415165357363898111835956182288689413415332700187138800163342528935995162909493886327294333783454800379993237576372926262416930647144015290354106493652889030302223064191324977053106297593241888901587847576970275305305448082887"),
					new BigInteger("24572756090675436655558989348367435657229027934850039134723547928298759493459210750763275821415365998249385058114785981171525775397529434899057014728428426923144106791982259796514324321640848981001358248859407903752571447929139072117650100161243770428835841578424868766229345464526762630277584983436721460351347")};
		}
		if(Utils.isEmpty(alg)||alg.equals("NONE")){
			alg=null;
		}
		
		StringCryptor sc=CryptFactory.getStringCryptor(alg, encode, Integer.parseInt(prs),code);
		String res=null;
		if(en){
			res=sc.encrypt(src);
		}else{
			res=sc.decrypt(src);
		}
		return new JSCommand("VM(this).fv('result','"+Utils.escapeXMLword(res)+"')");
	}

	@SuppressWarnings("deprecation")
	@RequestMapping("/comboBoxDemo")
	@ResponseBody
	public static View comboBoxDemo() {
		View view = new View();
		
		VerticalLayout root = new VerticalLayout("root").setMinwidth(200).setCls("bg-white x-bd-cand").setWmin(2).setHmin(2);
		view.add(root);
		GridPanel grid = new GridPanel("grid");
		root.add(grid, "*");
		grid.setHasTableHead(false).setNobr(true).setCls("x-grid-odd").setFace(GridPanel.FACE_NONE).setScroll(true);
		grid.setPub(new Tr().setHeight("30"));
		
		List<Object[]> gridData = new ArrayList<Object[]>();
		gridData.add(new Object[]{1, "学生"});
		gridData.add(new Object[]{2, "程序员"});
		gridData.add(new Object[]{3, "网管"});
		gridData.add(new Object[]{4, "清洁员"});
		
		grid.setCombo(new Combo().setField(new Combo.Field("v", "n").setSearch("v")));
		grid.setLimit(10);
		
		grid.setGridData(gridData);
		grid.addColumn(GridColumn.text(1, "n", "名称", "80%").setTipfield("n").setHighlight(new Highlight(0)));
		grid.addColumn(GridColumn.text(0, "v", "值", "20%").setTipfield("v").setAlign(GridColumn.ALIGN_RIGHT).setFormat("<span style='color:green;'>$v</span>"));
		
		PageBar page = new PageBar("page", PageBar.TYPE_MINI);
		page.setTarget("grid").setAlign(PageBar.ALIGN_RIGHT);
		page.setBtncount(5);
		root.add(page,"30");
		
		return view;
	}
	@SuppressWarnings("deprecation")
	@RequestMapping("/linkBoxDemo")
	@ResponseBody
	public static View linkBoxDemo() {
		View view = new View();
		
		VerticalLayout root = new VerticalLayout("root").setMinwidth(200).setCls("bg-white x-bd-cand").setWmin(2).setHmin(2);
		view.add(root);
		GridPanel grid = new GridPanel("grid");
		root.add(grid, "*");
		grid.setHasTableHead(false).setNobr(true).setCls("x-grid-odd").setFace(GridPanel.FACE_NONE).setScroll(true);
		grid.setPub(new Tr().setHeight("30"));
		
		List<Object[]> gridData = new ArrayList<Object[]>();
		gridData.add(new Object[]{1, "校一等"});
		gridData.add(new Object[]{2, "校二等"});
		gridData.add(new Object[]{3, "校三等"});
		
		grid.setCombo(new Combo().setField(new Combo.Field("v", "n").setSearch("v")));
		grid.setLimit(10);
		
		grid.setGridData(gridData);
		grid.addColumn(GridColumn.text(1, "n", "名称", "80%").setTipfield("n").setHighlight(new Highlight(0)));
		grid.addColumn(GridColumn.text(0, "v", "值", "20%").setTipfield("v").setAlign(GridColumn.ALIGN_RIGHT).setFormat("<span style='color:green;'>$v</span>"));
		
		PageBar page = new PageBar("page", PageBar.TYPE_MINI);
		page.setTarget("grid").setAlign(PageBar.ALIGN_RIGHT);
		page.setBtncount(5);
		root.add(page,"30");
		
		return view;
	}
	@SuppressWarnings("deprecation")
	@RequestMapping("/onlineBoxDemo")
	@ResponseBody
	public static View onlineBoxDemo() {
		View view = new View();
		
		VerticalLayout root = new VerticalLayout("root").setMinwidth(200).setCls("bg-white x-bd-cand").setWmin(2).setHmin(2);
		view.add(root);
		GridPanel grid = new GridPanel("grid");
		root.add(grid, "*");
		grid.setHasTableHead(false).setNobr(true).setCls("x-grid-odd").setFace(GridPanel.FACE_NONE).setScroll(true);
		grid.setPub(new Tr().setHeight("30"));
		
		List<Object[]> gridData = new ArrayList<Object[]>();
		gridData.add(new Object[]{1, "本科 "});
		gridData.add(new Object[]{2, "专科 "});
		gridData.add(new Object[]{3, "研究生 "});
		gridData.add(new Object[]{4, "博士后 "});
		
		grid.setCombo(new Combo().setField(new Combo.Field("v", "n").setSearch("v")));
		grid.setLimit(10);
		
		grid.setGridData(gridData);
		grid.addColumn(GridColumn.text(1, "n", "名称", "80%").setTipfield("n").setHighlight(new Highlight(0)));
		grid.addColumn(GridColumn.text(0, "v", "值", "20%").setTipfield("v").setAlign(GridColumn.ALIGN_RIGHT).setFormat("<span style='color:green;'>$v</span>"));
		
		PageBar page = new PageBar("page", PageBar.TYPE_MINI);
		page.setTarget("grid").setAlign(PageBar.ALIGN_RIGHT);
		page.setBtncount(5);
		root.add(page,"30");
		
		return view;
	}
	public class User {
		@Data4GridPanel(name="id", label="", order=0, type=ColumnType.HIDDEN, checkbox=true, radio=true)
		@Data4FlexGrid(name="id", label="", order=0, type=NodeType.HIDDEN)
		@Data4FormPanel(name="id", label="", order=0, type=NodeType.HIDDEN)
		private String id;
		//改用对get注解
		private String name;
		@Data4FlexGrid(name="sex", label="性别", order=2, type=NodeType.RADIO, occupy=4)
		@Data4FormPanel(name="sex", label="性别", order=2, type=NodeType.RADIO, fromRow=1, fromColumn=0)
		private boolean sex;
		@Data4FlexGrid(name="sex", type=NodeType.OPTIONS)
		@Data4FormPanel(name="sex", type=NodeType.OPTIONS)
		private List<Object[]> sexList;
		@Data4FlexGrid(name="hobby", label="爱好", order=3, type=NodeType.CHECKBOX, occupy=4)
		@Data4FormPanel(name="hobby", label="爱好", order=3, type=NodeType.CHECKBOX, fromRow=2, fromColumn=0)
		private List<Integer> hobby;
		@Data4FlexGrid(name="hobby", type=NodeType.OPTIONS)
		@Data4FormPanel(name="hobby", type=NodeType.OPTIONS)
		private List<Object[]> hobbies;
		//改用对set注解
		private String introduction;
		@Data4FlexGrid(name="password", label="密码", order=5, type=NodeType.PASSWORD, occupy=4)
		@Data4FormPanel(name="password", label="密码", order=5, type=NodeType.PASSWORD, fromRow=4, fromColumn=0)
		private String password;
		@Data4GridPanel(name="money", label="资产", order=6, type=ColumnType.TEXT)
		@Data4FlexGrid(name="money", label="资产", order=6, type=NodeType.SPINNER, occupy=4)
		@Data4FormPanel(name="money", label="资产", order=6, type=NodeType.SPINNER, fromRow=5, fromColumn=0)
		private Number money;
		@Data4FlexGrid(name="birthday", label="出生日期", order=7, type=NodeType.DATEPICKER, occupy=4)
		@Data4FormPanel(name="birthday", label="出生日期", order=7, type=NodeType.DATEPICKER, fromRow=6, fromColumn=0)
		private Date birthday;
		@Data4FlexGrid(name="birthOfParents", label="父母生日", order=8, type=NodeType.MULDATEPICKER, occupy=4)
		@Data4FormPanel(name="birthOfParents", label="父母生日", order=8, type=NodeType.MULDATEPICKER, fromRow=7, fromColumn=0)
		private Date birthOfParents;
		@Data4FlexGrid(name="vipTime", label="VIP起止日期", order=9, type=NodeType.PERIOD, occupy=4, format=DatePicker.DATE_TIME_FULL)
		@Data4FormPanel(name="vipTime", label="VIP起止日期", order=9, type=NodeType.PERIOD, fromRow=8, fromColumn=0, format=DatePicker.DATE_TIME_FULL)
		private Date[] vipTime;
		@Data4FlexGrid(name="vipLevel", label="VIP等级", order=10, type=NodeType.SELECT, occupy=4)
		@Data4FormPanel(name="vipLevel", label="VIP等级", order=10, type=NodeType.SELECT, fromRow=9, fromColumn=0)
		private int vipLevel;
		@Data4FlexGrid(name="vipLevel", type=NodeType.OPTIONS)
		@Data4FormPanel(name="vipLevel", type=NodeType.OPTIONS)
		private List<Integer> vipLevelList;
		@Data4FlexGrid(name="vipKind", label="VIP类型", order=11, type=NodeType.XBOX, occupy=4)
		@Data4FormPanel(name="vipKind", label="VIP类型", order=11, type=NodeType.XBOX, fromRow=10, fromColumn=0)
		private String vipKind;
		@Data4FlexGrid(name="vipKind", type=NodeType.OPTIONS)
		@Data4FormPanel(name="vipKind", type=NodeType.OPTIONS)
		private List<String> vipKindList;
		@Data4FlexGrid(name="occupation", label="职业", order=12, type=NodeType.COMBOBOX, src="misc/comboBoxDemo", occupy=4, dropSrc="misc/comboBoxDemo")
		@Data4FormPanel(name="occupation", label="职业", order=12, type=NodeType.COMBOBOX, src="misc/comboBoxDemo", fromRow=11, fromColumn=0, dropSrc="misc/comboBoxDemo")
		private int occupation;
		@Data4FlexGrid(name="prize", label="奖项", order=13, type=NodeType.LINKBOX, src="misc/linkBoxDemo", occupy=4, dropSrc="misc/linkBoxDemo")
		@Data4FormPanel(name="prize", label="奖项", order=13, type=NodeType.LINKBOX, src="misc/linkBoxDemo", fromRow=12, fromColumn=0, dropSrc="misc/linkBoxDemo")
		private int prize;
		//同时对字段/get/set注解
		@Data4GridPanel(name="education", label="学历", order=14, type=ColumnType.TEXT)
		@Data4FlexGrid(name="education", label="学历", order=14, type=NodeType.ONLINEBOX, src="misc/onlineBoxDemo", occupy=4, dropSrc="misc/onlineBoxDemo")
		@Data4FormPanel(name="education", label="学历", order=14, type=NodeType.ONLINEBOX, src="misc/onlineBoxDemo", fromRow=13, fromColumn=0, dropSrc="misc/onlineBoxDemo")
		private String education;
		@Data4FlexGrid(name="remark", order=15, type=NodeType.HTML, occupy=4)
		@Data4FormPanel(name="remark", order=15, type=NodeType.HTML, fromRow=13, fromColumn=0)
		private String remark;
		
		public User(String id, String name, boolean sex, List<Object[]> sexList, List<Integer> hobby, List<Object[]> hobbies, String introduction,
				String password, Number money, Date birthday, Date birthOfParents, Date[] vipTime, int vipLevel, List<Integer> vipLevelList, 
				String vipKind, List<String>vipKindList, int occupation, int prize, String education, String remark) {
			this.id=id;
			this.name=name;
			this.sex=sex;
			this.sexList=sexList;
			this.hobbies=hobbies;
			this.hobby=hobby;
			this.introduction=introduction;
			this.password=password;
			this.money=money;
			this.birthday=birthday;
			this.birthOfParents=birthOfParents;
			this.vipTime=vipTime;
			this.vipLevel=vipLevel;
			this.vipLevelList=vipLevelList;
			this.vipKind=vipKind;
			this.vipKindList=vipKindList;
			this.occupation=occupation;
			this.prize=prize;
			this.education=education;
			this.remark=remark;
		}
		public String getRemark() {
			return remark;
		}
		public void setRemark(String remark) {
			this.remark = remark;
		}
		@Data4GridPanel(name="education", label="学历", order=14, type=ColumnType.TEXT)
		@Data4FlexGrid(name="education", label="学历", order=14, type=NodeType.ONLINEBOX, src="misc/onlineBoxDemo", occupy=4, dropSrc="misc/onlineBoxDemo")
		@Data4FormPanel(name="education", label="学历", order=14, type=NodeType.ONLINEBOX, src="misc/onlineBoxDemo", fromRow=13, fromColumn=0, dropSrc="misc/onlineBoxDemo")
		public String getEducation() {
			return education;
		}
		@Data4GridPanel(name="education", label="学历", order=14, type=ColumnType.TEXT)
		@Data4FlexGrid(name="education", label="学历", order=14, type=NodeType.ONLINEBOX, src="misc/onlineBoxDemo", occupy=4, dropSrc="misc/onlineBoxDemo")
		@Data4FormPanel(name="education", label="学历", order=14, type=NodeType.ONLINEBOX, src="misc/onlineBoxDemo", fromRow=13, fromColumn=0, dropSrc="misc/onlineBoxDemo")
		public void setEducation(String education) {
			this.education = education;
		}
		public int getOccupation() {
			return occupation;
		}
		public void setOccupation(int occupation) {
			this.occupation = occupation;
		}
		//不实现get方法
		public void setPrize(int prize) {
			this.prize = prize;
		}
		public String getIntroduction() {
			return introduction;
		}
		@Data4GridPanel(name="introduction", label="个人简介", order=4, type=ColumnType.TEXT, format="<a>个人简介<a>")
		@Data4FlexGrid(name="introduction", label="个人简介", order=4, type=NodeType.TEXTAREA, occupy=4)
		@Data4FormPanel(name="introduction", label="个人简介", order=4, type=NodeType.TEXTAREA, fromRow=3, fromColumn=0)
		public void setIntroduction(String introduction) {
			this.introduction = introduction;
		}
		public int getVipLevel() {
			return vipLevel;
		}
		public void setVipLevel(int vipLevel) {
			this.vipLevel = vipLevel;
		}
		public List<Integer> getVipLevelList() {
			return vipLevelList;
		}
		public void setVipLevelList(List<Integer> vipLevelList) {
			this.vipLevelList = vipLevelList;
		}
		public String getVipKind() {
			return vipKind;
		}
		public void setVipKind(String vipKind) {
			this.vipKind = vipKind;
		}
		public List<String> getVipKindList() {
			return vipKindList;
		}
		public void setVipKindList(List<String> vipKindList) {
			this.vipKindList = vipKindList;
		}
		public List<Object[]> getSexList() {
			return sexList;
		}
		public void setSexList(List<Object[]> sexList) {
			this.sexList = sexList;
		}
		public Date[] getVipTime() {
			return vipTime;
		}
		public void setVipTime(Date[] vipTime) {
			this.vipTime = vipTime;
		}
		public Date getBirthOfParents() {
			return birthOfParents;
		}
		public void setBirthOfParents(Date birthOfParents) {
			this.birthOfParents = birthOfParents;
		}
		public Date getBirthday() {
			return birthday;
		}
		public void setBirthday(Date birthday) {
			this.birthday = birthday;
		}
		public String getPassword() {
			return password;
		}
		public void setPassword(String password) {
			this.password = password;
		}
		public Number getMoney() {
			return money;
		}
		public void setMoney(Number money) {
			this.money = money;
		}
		public String getId() {
			return id;
		}
		public void setId(String id) {
			this.id = id;
		}
		@Data4FormPanel(name="name", label="姓名", order=1, type=NodeType.TEXT, fromColumn=0, fromRow=0)
		@Data4GridPanel(name="name", label="姓名", order=1, type=ColumnType.TEXT)
		@Data4FlexGrid(name="name", label="姓名", order=1, type=NodeType.TEXT, occupy=4)
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public boolean isSex() {
			return sex;
		}
		public void setSex(boolean sex) {
			this.sex = sex;
		}
		public List<Integer> getHobby() {
			return hobby;
		}
		public void setHobby(List<Integer> hobby) {
			this.hobby = hobby;
		}
		public List<Object[]> getHobbies() {
			return hobbies;
		}
		public void setHobbies(List<Object[]> hobbies) {
			this.hobbies = hobbies;
		}
	}
	private static Object getValue(Method method, Field field, Object entity) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		if (method == null) {
			field.setAccessible(true);
			return field.get(entity);
		} else {
			return method.invoke(entity);
		}
	}
	private static Field getField4Method(Method method, Class<? extends Object> clz) {
		String methodName = method.getName();
		String fieldName = null;
		if ("is".equals(methodName.substring(0, 2))) {
			fieldName = methodName.substring(2, methodName.length());
		} else if ("get".equals(methodName.substring(0, 3)) || "set".equals(methodName.substring(0, 3))) {
			fieldName = methodName.substring(3, methodName.length());
		}
		if (Utils.isEmpty(fieldName)) {
			return null;
		}
		//首字母小写
		fieldName = Character.toLowerCase(fieldName.charAt(0)) + fieldName.substring(1, fieldName.length());
		
        Field[] fields = clz.getDeclaredFields(); 
        Field field = null;
		for (Field f : fields) {
			if (f.getName().equals(fieldName)) {
				field = f;
				break;
			}
		}
		return field;
	}
	private static Method getMethod4Field(Field field, Class<? extends Object> clz) {
		String fieldName = field.getName();
		//首字母大写
		fieldName = Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1, fieldName.length());
		//生成对应的get方法
		String methodString;
		if (field.getType() == boolean.class) {
			methodString = "is"+fieldName;
		} else {
			methodString = "get"+fieldName;
		}
        Method[] methods = clz.getDeclaredMethods(); 
        Method method = null;
		for (Method m : methods) {
			if (m.getName().equals(methodString)) {
				method = m;
				break;
			}
		}
		return method;
	}
	private static Widget<?> getOptionsWidget(Data4Ui anno, Object entity, Object value, List<Data4Ui> annoList, Map<String, List<Object[]>> name2Options) {
		//找出所有选项的列表
		List<Object[]> optionList = null;
		for (Data4Ui options : annoList) {
			if (options.type() == NodeType.OPTIONS && options.name().equals(anno.name())) {
				optionList = name2Options.get(options.name());
				break;
			}
		}
		if(optionList != null) {
			if (NodeType.CHECKBOX == anno.type()) {
				@SuppressWarnings("unchecked")
				List<Object> checkList = (List<Object>)value;
				return new Checkboxgroup(anno.name(), anno.label(), checkList, optionList).setRequired(anno.required());
			} else if (NodeType.RADIO == anno.type()) {
				Object checkObject = value;
				return new Radiogroup(anno.name(), anno.label(), checkObject, optionList).setRequired(anno.required());
			} else if (NodeType.SELECT == anno.type()) {
				Object checkObject = value;
				return new Select(anno.name(), anno.label(), checkObject, optionList).setRequired(anno.required());
			} else if (NodeType.XBOX == anno.type()) {
				Object checkObject = value;
				return new Xbox(anno.name(), anno.label(), checkObject, optionList).setRequired(anno.required());
			}
		}
		return null;
	}
	
	private static Widget<?> getWidget(Data4Ui anno, Object entity, Object value) {
		NodeType type = anno.type();
		if (NodeType.TEXT == type) {
			return new Text(anno.name(), anno.label(), value.toString()).setRequired(anno.required());
		} else if (NodeType.PASSWORD == type) {
			return new Password(anno.name(), anno.label(), value.toString()).setRequired(anno.required());
		} else if (NodeType.TEXTAREA == type) {
			return new Textarea(anno.name(), anno.label(), value.toString());
		} else if (NodeType.HTML == type) {
			return new Html(anno.name(), value.toString());
		} else if (NodeType.SPINNER == type) {
			Double minValue = anno.minValue();
			if (minValue == Double.MIN_VALUE) {
				minValue = null;
			}
			Double maxValue = anno.maxValue();
			if (maxValue == Double.MAX_VALUE) {
				maxValue = null;
			}
			Double step = anno.step();
			if (step == 1) {
				step = null;
			}
			return new Spinner(anno.name(), anno.label(), (Number)value, minValue, maxValue, step).setRequired(anno.required());
		} else if (NodeType.DATEPICKER == type) {
			String format = anno.format();
			if ("".equals(format)) {
				format = DatePicker.DATE;
			}
			return new DatePicker(anno.name(), anno.label(), value, format).setRequired(anno.required());
		} else if (NodeType.MULDATEPICKER == type) {
			String format = anno.format();
			if ("".equals(format)) {
				format = MuldatePicker.DATE;
			}
			return new MuldatePicker(anno.name(), anno.label(), value, format).setRequired(anno.required());
		} else if (NodeType.PERIOD == type) {
			Date[] periodDates = (Date[])value;
			String format = anno.format();
			if ("".equals(format)) {
				format = DatePicker.DATE;
			}
			DatePicker beginTime = new DatePicker(anno.name(), anno.label(), periodDates[0], format).setRequired(anno.required());
			DatePicker endTime = new DatePicker(anno.name(), anno.label(), periodDates[1], format).setRequired(anno.required());
			return new Period(anno.label(), beginTime, endTime);
		} else if (NodeType.COMBOBOX == type) {
			Combobox combobox = new Combobox(anno.name(), anno.label(), value.toString(), anno.src()).setRequired(anno.required());
			if (!Utils.isEmpty(anno.dropSrc())) {
				combobox.setDropsrc(anno.dropSrc());
			}
			return combobox;
		} else if (NodeType.LINKBOX == type) {
			Linkbox linkbox = new Linkbox(anno.name(), anno.label(), value.toString(), anno.src()).setRequired(anno.required());
			if (!Utils.isEmpty(anno.dropSrc())) {
				linkbox.setDropsrc(anno.dropSrc());
			}
			return linkbox;
		} else if (NodeType.ONLINEBOX == type) {
			Onlinebox onlinebox = new Onlinebox(anno.name(), anno.label(), value.toString(), anno.src()).setRequired(anno.required());
			if (!Utils.isEmpty(anno.dropSrc())) {
				onlinebox.setDropsrc(anno.dropSrc());
			}
			return onlinebox;
		} else {
			return null;
		}
	}
	@SuppressWarnings("unchecked")
	private static Map<String, List<Object[]>> getName2Options(
			Class<? extends Object> clz,List<Data4Ui> annoList,Map<Data4Ui, Field> anno2Field,Object entity ) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		Map<String, List<Object[]>> name2Options = new HashMap<String, List<Object[]>>();
		for (Data4FormPanel anno : annoList) {
			if (anno.type() == NodeType.OPTIONS) {
				Method method = getMethod4Field(anno2Field.get(anno), clz);
				Object value = getValue(method, anno2Field.get(anno), entity);
				name2Options.put(anno.name(), (List<Object[]>)value);
			}
		}
		return name2Options;
	}
	/**
	 * 通过注解生成一个FormPanel
	 * @param entity
	 * @return FormPanel
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 */
	public static FormPanel formPanelByAnno(Object entity) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		Class<? extends Object> clz = entity.getClass();
		List<Data4Ui> annoList = new ArrayList<Data4Ui>();
		Map<Data4Ui, Field> anno2Field = new HashMap<Data4Ui, Field>();
		analyzeAnno(clz, Data4FormPanel.class, annoList, anno2Field);
		FormPanel formPanel = new FormPanel(null);
		Map<String, List<Object[]>> name2Options = getName2Options(clz,annoList,anno2Field,entity);
		for (Data4FormPanel anno : annoList) {
			Field field = anno2Field.get(anno);
			NodeType type = anno.type();
			Method method = getMethod4Field(field, clz);
			Object value = getValue(method, field, entity);
			if (NodeType.HIDDEN == type) {
				formPanel.addHidden(anno.name(), value.toString());
			} else if (NodeType.CHECKBOX == type || NodeType.RADIO == type || NodeType.SELECT == type ||NodeType.XBOX == type) {
				formPanel.add(getOptionsWidget(new Data4Ui(anno), entity, value, annoList, name2Options));
			} else {
				Data4Ui data = new Data4Ui(anno);
				formPanel.add(getWidget(data, entity, value));
			}
		}
		return formPanel;
	}
	

	/**
	 * 通过注解生成一个GridLayoutFormPanel
	 * @param entity
	 * @return GridLayoutFormPanel
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 */
	public static GridLayoutFormPanel gridLayoutFormPanelByAnno(Object entity) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		Class<? extends Object> clz = entity.getClass();
		List<Data4Ui> annoList = new ArrayList<Data4Ui>();
		Map<Data4Ui, Field> anno2Field = new HashMap<Data4Ui, Field>();
		analyzeAnno(clz, Data4FormPanel.class, annoList, anno2Field);
		GridLayoutFormPanel gridLayoutFormPanel = new GridLayoutFormPanel(null);
		Map<String, List<Object[]>> name2Options = getName2Options(clz,annoList,anno2Field,entity);
		for (Data4FormPanel anno : annoList) {
			Field field = anno2Field.get(anno);
			NodeType type = anno.type();
			Method method = getMethod4Field(field, clz);
			Object value = getValue(method, field, entity);
			if (NodeType.HIDDEN == type) {
				gridLayoutFormPanel.addHidden(anno.name(), value.toString());
			}
			if (anno.toColumn() >= 0 && anno.toRow() >= 0) {
				if (NodeType.CHECKBOX == type) {
					gridLayoutFormPanel.add(anno.fromRow(), anno.fromColumn(), anno.toRow(), anno.toColumn(), getOptionsWidget(new Data4Ui(anno), entity, value, annoList, name2Options));
				} else {
					gridLayoutFormPanel.add(anno.fromRow(), anno.fromColumn(), anno.toRow(), anno.toColumn(), getWidget(new Data4Ui(anno), entity, value));
				}
			} else {
				if (NodeType.CHECKBOX == type || NodeType.RADIO == type || NodeType.SELECT == type || NodeType.XBOX == type) {
					gridLayoutFormPanel.add(anno.fromRow(), anno.fromColumn(), getOptionsWidget(new Data4Ui(anno), entity, value, annoList, name2Options));
				} else {
					gridLayoutFormPanel.add(anno.fromRow(), anno.fromColumn(), getWidget(new Data4Ui(anno), entity, value));
				}
			}
		}
		return gridLayoutFormPanel;
	}
	/**
	 * 通过注解生成一个FlexGrid
	 * @param entity
	 * @return FlexGrid
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 */
	public static FlexGrid flexGridByAnno(Object entity) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		Class<? extends Object> clz = entity.getClass();
		List<Data4Ui> annoList = new ArrayList<Data4Ui>();
		Map<Data4Ui, Field> anno2Field = new HashMap<Data4Ui, Field>();
		analyzeAnno(clz, Data4FlexGrid.class, annoList, anno2Field);
		FlexGrid flexGrid = new FlexGrid(null);
		Map<String, List<Object[]>> name2Options = getName2Options(clz,annoList,anno2Field,entity);
		for (Data4FlexGrid anno : annoList) {
			Field field = anno2Field.get(anno);
			NodeType type = anno.type();
			Method method = getMethod4Field(field, clz);
			Object value = getValue(method, field, entity);
			if (NodeType.HIDDEN == type) {
				flexGrid.addHidden(anno.name(), value.toString());
			} else if (NodeType.CHECKBOX == type || NodeType.RADIO == type || NodeType.SELECT == type || NodeType.XBOX == type) {
				flexGrid.add(getOptionsWidget(new Data4Ui(anno), entity, value, annoList, name2Options), anno.occupy());
			} else if (NodeType.OPTIONS != type) {
				Data4Ui data = new Data4Ui(anno);
				flexGrid.add(getWidget(data, entity, value), anno.occupy());
			}
		}
		return flexGrid;
	}
	/**
	 * 通过注解生成一个GridPanel
	 * @param entity
	 * @return FlexGrid
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 */
	public static GridPanel gridPanelByAnno(List<? extends Object> entities) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		Class<? extends Object> clz = entities.get(0).getClass();
		List<Data4GridPanel> annoList = new ArrayList<Data4GridPanel>();
		Map<Data4GridPanel, Field> anno2Field = new HashMap<Data4GridPanel, Field>();
		Set<String> annoNameSet = new HashSet<String>();
		Field[] fields = clz.getDeclaredFields();
		for(Field field : fields){
			// 解析字段上是否有注解
			if(field.isAnnotationPresent(Data4GridPanel.class)) {
				Data4GridPanel anno = field.getAnnotation(Data4GridPanel.class);
				if (annoNameSet.contains(anno.name())) {
					continue;
				} else {
					annoNameSet.add(anno.name());
				}
				annoList.add(anno);
				anno2Field.put(anno, field);
			}
		}
		Method[] methods = clz.getDeclaredMethods();
		for(Method method : methods){
			// 解析字段上是否有注解
			if(method.isAnnotationPresent(Data4GridPanel.class)) {
				Data4GridPanel anno = method.getAnnotation(Data4GridPanel.class);
				if (annoNameSet.contains(anno.name())) {
					continue;
				} else {
					annoNameSet.add(anno.name());
				}
				annoList.add(anno);
				anno2Field.put(anno, getField4Method(method, clz));
			}
		}
		//排序
		Collections.sort(annoList, new Comparator<Data4GridPanel>() {
			@Override
			public int compare(Data4GridPanel o1, Data4GridPanel o2) {
				return o1.order()-o2.order();
			}
		});
		GridPanel gridPanel = new GridPanel(null);
		int dataColumnIndex = 0;
		for (Data4GridPanel anno : annoList) {
			ColumnType type = anno.type();
			if (ColumnType.TEXT == type) {
				GridColumn column = GridColumn.text(dataColumnIndex++, anno.name(), anno.label(), "*");
				if (!"".equals(anno.format())) {
					column.setFormat(anno.format());
				}
				gridPanel.addColumn(column);
			} else if (ColumnType.HIDDEN == type) {
				gridPanel.addColumn(GridColumn.hidden(dataColumnIndex++, "saleId"));
			}
			if (anno.checkbox()) {
				gridPanel.addColumn(GridColumn.checkbox(anno.name(), anno.width()));
			}
			if (anno.radio()) {
				gridPanel.addColumn(GridColumn.radio(anno.name(), anno.width()));
			}
		}
		List<Object[]> gridData = new ArrayList<Object[]>(entities.size());
		for (Object entity : entities) {
			Object[] data = new Object[annoList.size()];
			int index=0;
			for (Data4GridPanel anno : annoList) {
				Field field = anno2Field.get(anno);
				Method method = getMethod4Field(field, clz);
				Object value = getValue(method, field, entity);
				data[index++] = value.toString();
			}
			gridData.add(data);
		}
		gridPanel.setGridData(gridData);
		return gridPanel;
	}
	/**
	 * 用反射将字段中的注解解析出来,并按order大小排序
	 * @param entity
	 * @param annoList
	 * @param anno2Field
	 */
	public static void analyzeAnno(Class<? extends Object> objClz, Class<? extends Annotation> annoClz, List<Data4Ui> annoList, Map<Data4Ui, Field> anno2Field) {
		
		Set<String> annoNameSet = new HashSet<String>();
		Field[] fields = objClz.getDeclaredFields();
		for(Field field : fields){
			Data4Ui data = new Data4Ui();
			// 解析字段上是否有注解
			if(annoClz==Data4FormPanel.class && field.isAnnotationPresent(Data4FormPanel.class)) {
				Data4FormPanel anno = field.getAnnotation(Data4FormPanel.class);
				data.setData4FormPanel(anno);
			} else if(annoClz==Data4FlexGrid.class && field.isAnnotationPresent(Data4FlexGrid.class)) {
				Data4FlexGrid anno = field.getAnnotation(Data4FlexGrid.class);
				data.setData4FlexGrid(anno);
			}
			if (data.type() != NodeType.OPTIONS && annoNameSet.contains(data.name())) {
				continue;
			} else {
				annoNameSet.add(data.name());
			}
			if (!data.isEmpty()) {
				annoList.add(data);
				anno2Field.put(data, field);
			}
		}
		Method[] methods = objClz.getDeclaredMethods();
		for (Method method : methods) {
			Data4Ui data = new Data4Ui();
			// 解析方法上是否有注解
			if(annoClz==Data4FormPanel.class && method.isAnnotationPresent(Data4FormPanel.class)) {
				Data4FormPanel anno = method.getAnnotation(Data4FormPanel.class);
				data.setData4FormPanel(anno);
			} else if(annoClz==Data4FlexGrid.class && method.isAnnotationPresent(Data4FlexGrid.class)) {
				Data4FlexGrid anno = method.getAnnotation(Data4FlexGrid.class);
				data.setData4FlexGrid(anno);
			}
			if (data.type() != NodeType.OPTIONS && annoNameSet.contains(data.name())) {
				continue;
			} else {
				annoNameSet.add(data.name());
			}
			if (!data.isEmpty()) {
				annoList.add(data);
				anno2Field.put(data, getField4Method(method, objClz));
			}
		}
		//排序
		Collections.sort(annoList, new Comparator<Data4Ui>() {
			@Override
			public int compare(Data4Ui o1, Data4Ui o2) {
				return o1.order()-o2.order();
			}
		});
	}
	@RequestMapping("/userDemo")
	@ResponseBody
	public Object userDemo(HttpServletRequest request) throws Exception {
		View view = new View();

		VerticalLayout root = new VerticalLayout(null);
		view.add(root);
		
		List<Object[]> sexList = new ArrayList<Object[]>();
		sexList.add(new Object[]{true, "男"});
		sexList.add(new Object[]{false, "女"});
		
		List<Integer> hobby = new ArrayList<Integer>();
		hobby.add(1);
		hobby.add(2);
		
		List<Object[]> hobbies = new ArrayList<Object[]>();
		hobbies.add(new Object[]{1, "打球"});
		hobbies.add(new Object[]{2, "编码"});
		hobbies.add(new Object[]{3, "绘画"});
		
		Date[] vipTime = new Date[2];
		vipTime[0] = new Date();
		vipTime[1] = new Date();
		
		List<Integer> vipLevels = new ArrayList<Integer>();
		vipLevels.add(1);
		vipLevels.add(2);
		vipLevels.add(3);
		vipLevels.add(4);
		vipLevels.add(5);
		
		List<String> vipKinds = new ArrayList<String>();
		vipKinds.add("普通VIP");
		vipKinds.add("尊贵VIP");
		
		User user = new User("666", "小红", false, sexList, hobby, hobbies, "这是一段介绍文本", "123456", 123, new Date(), new Date(),
				vipTime, 2, vipLevels, "尊贵VIP", vipKinds, 1, 1, "本科", "备注：无");
		
		List<User> users = new ArrayList<User>();
		users.add(user);
		users.add(user);
		users.add(user);
		users.add(user);
		users.add(user);
		users.add(user);
		root.add(gridPanelByAnno(users).setScroll(true));
		root.add(formPanelByAnno(user).setScroll(true));
		root.add(flexGridByAnno(user).setScroll(true));
		root.add(gridLayoutFormPanelByAnno(user).setScroll(true));

		root.add(new SubmitButton("提交").setHeight("40").setCls("btn").setOn(Button.EVENT_CLICK, "this.cmd({type:'submit',src:'gridShow/save'})"));
		return view;
	}
	@RequestMapping("/cmdDialog")
	@ResponseBody
	public Object cmdDialog(HttpServletRequest request) throws Exception {
		View view = new View();
		HorizontalLayout root = new HorizontalLayout(null);
		view.add(root);
		
		root.add(new Html("<p align=center>这是被打开的对话框</p>"));
		return view;
	}
	@SuppressWarnings("deprecation")
	@RequestMapping("/pickboxDialog")
	@ResponseBody
	public Object pickboxDialog(HttpServletRequest request) throws Exception {
			View view = new View();
			
			VerticalLayout root = new VerticalLayout("root").setMinwidth(300).setCls("bg-white x-bd-cand");
			view.add(root);
			GridPanel grid = new GridPanel("grid");
			root.add(grid, "*");
			grid.setHasTableHead(false).setNobr(true).setCls("x-grid-odd").setFace(GridPanel.FACE_NONE).setScroll(true);
			grid.setPub(new Tr().setHeight("30").setOn(Tr.EVENT_CLICK, 
					"var text=this.data('v');var value=this.data('n');$.dialog(this).commander.val(value,text);$.close(this)"));
			List<Object[]> gridData = new ArrayList<Object[]>();
			gridData.add(new Object[]{"小名","aaa"});
			gridData.add(new Object[]{"小红","bbb"});
			gridData.add(new Object[]{"小白","ccc"});
			gridData.add(new Object[]{"小黑","ddd"});
			gridData.add(new Object[]{"小鸡","eee"});
			gridData.add(new Object[]{"小鸭","fff"});
			gridData.add(new Object[]{"小狗","ggg"});
			gridData.add(new Object[]{"小猪","hhh"});
			grid.setCombo(new Combo().setField(new Combo.Field("v", "n").setSearch("v")));
			grid.setLimit(10);
			
			grid.setGridData(gridData);
			grid.addColumn(GridColumn.text(1, "n", "名称", "40%").setTipfield("n"));
			grid.addColumn(GridColumn.text(0, "v", "值", "20%").setTipfield("v").setAlign(GridColumn.ALIGN_RIGHT).setFormat("<span style='color:green;'>$v</span>"));
			
		return view;
	}
}
